package sameClasses;

import java.io.Serializable;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.security.spec.InvalidKeySpecException;

public class User implements Serializable {

  private static final long serialVersionUID = 1L;
  private String username;
  private byte[] salt;              // serverside
  private boolean loggedIn = false; // serverside
  
  private byte[] hashedpassword;    // 32Byte = 256Bit - created on both sides and then verified on the server

  // constructor called by server - the salt is created here
  public User(String username, char[] password) throws NoSuchAlgorithmException, InvalidKeySpecException {
    this.username = username;

    SecureRandom ranGen = new SecureRandom();
    this.salt = new byte[32]; // 256 Bit
    ranGen.nextBytes(this.salt);

    this.hashedpassword = Crypter.buildSecretBytes(password, salt);

    password = null;
  }

  // first client-constructor - only username for verification on server and at success we will get the salt back
  public User(String username) {
    this.username = username;
    this.hashedpassword = null;
    this.salt = null;
  }

  // future - not used now
  public User(String username, char[] password, byte[] loginSalt) throws NoSuchAlgorithmException, InvalidKeySpecException {
    this.username = username;
    this.hashedpassword = Crypter.buildSecretBytes(password, loginSalt);

    password = null;
  }

  public byte[] getSalt() {
    return this.salt;
  }

  public void setSalt(byte[] salt) {
    this.salt = salt;
  }

  // serverside: a user's password got changed, so the salt gets changed aswell
  public void changePassword(char[] password) throws NoSuchAlgorithmException, InvalidKeySpecException {
    SecureRandom ranGen = new SecureRandom();
    this.salt = new byte[32]; // 32 Byte = 256 Bit
    ranGen.nextBytes(this.salt);

    this.hashedpassword = Crypter.buildSecretBytes(password, this.salt);
  }
  
  // clientside: we already got the salt by the server and create our derived secret now
  public void changePasswordWithSalt(char[] password, byte[] salt) throws NoSuchAlgorithmException, InvalidKeySpecException {
    this.hashedpassword = Crypter.buildSecretBytes(password, salt);
  }

  public String getName() {
    return new String(this.username);
  }

  public byte[] getHashedPassword() {
    return this.hashedpassword;
  }

  // serverside: on pre-client-login - only check the username
  @Override
  public boolean equals(Object obj) {
    User a = (User) obj;
    if (this.getName().equals(a.getName())) {
      return true;
    }
    return false;
  }

  // serverside: issued when a user wants to login
  public boolean equalsAll(User user) {
    if (this.getName().equals(user.getName())
        && this.getHashedPassword().equals(user.getHashedPassword())) {
      return true;
    }
    return false;
  }

  @Override
  public String toString() {
    return new String("Username:" + this.username.toString());
  }

  public boolean LoggedIn() {
    return this.loggedIn;
  }

  public boolean login() {
    return this.loggedIn = true;
  }

  public boolean logout() {
    return this.loggedIn = false;
  }

}
